package indi.mozping.pc;

import indi.mozping.tools.SleepTools;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author by mozping
 * @Classname PcCondition
 * @Description TODO
 * ��ʹ��singal��ʱ���������������⣺
 * 1.ĳһʱ�̣�������������֮����Ʒ���ˣ�Ȼ��������await�ȴ������ѣ������ͷţ�
 * 2.������1�õ�����Ȼ�����ѵ���Ʒ���ٵ���singal��������1�����ͷ�
 * 3.������2��������1��singal���ѣ�����û�п����ѵ���Ʒ��Ȼ���await�ȴ��Լ��������߻��ѣ�������2�ͷ���
 * 4.������1�õ��������ֲ������ѣ�Ҳ����await�����������ߺ�2�������߶�������
 * <p>
 * 1.�����ԭ������singal������ͬ�࣬����2������3��������ͬ�ർ��������û�б����ѣ����Լ���֤��singalAllû�����������⣬��ػ���ȫ���ȴ���һ��condition���߳�
 * 2.�ڶ�����������await֮ǰ����singal�źţ�������û���ʹ��singalAll��������ʹ�Լ�Ҫ������Ҳ�ỽ���������̱߳�����ǰ��ĵ��Ĳ�* ����ȫ������
 * 3.���Ƽ��ķ����ǵ�����������ʹ��2��Condition�������ߺ������ߵȴ��ڲ�ͬ��Condition������˲�����ֻ���ͬ������
 * @Date 2019/8/12 17:36
 */
public class PcConditionBug {

    private static ReentrantLock lock = new ReentrantLock();
    private static Condition condition = lock.newCondition();
    private static LinkedList<Object> buffer = new LinkedList<>();
    private static final int MAX = 5;

    public static void main(String[] args) {
        new Thread(new Producer()).start();
        new Thread(new Producer()).start();
        new Thread(new Consumer()).start();
        new Thread(new Consumer()).start();
    }


    static class Producer implements Runnable {

        @Override
        public void run() {
            while (true) {
                lock.lock();
                try {
                    while (buffer.size() >= MAX) {
                        System.out.println("����...");
                        try {
                            condition.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    if (buffer.size() < MAX) {
                        buffer.add(new Object());
                        System.out.println("����һ��...������������" + buffer.size());
                        condition.signal();
                        SleepTools.randomMs(50);
                    }
                } finally {
                    lock.unlock();
                }
            }
        }
    }

    static class Consumer implements Runnable {

        @Override
        public void run() {
            while (true) {
                lock.lock();
                try {
                    while (buffer.size() <= 0) {
                        System.out.println("����...");
                        try {
                            condition.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    if (buffer.size() > 0) {
                        buffer.removeFirst();
                        System.out.println("����һ��...���Ѻ�������" + buffer.size());
                        condition.signal();
                        SleepTools.randomMs(50);
                    }
                } finally {
                    lock.unlock();
                }
            }
        }
    }
}